#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "queue.h"
#include "mongoose.h"
#include "uri_handler.h"
#include "object.h"
#include "currency.h"

static struct object_list_t currencies = LIST_HEAD_INITIALIZER();

static unsigned int get_currency_id(void)
{
	/* XXX multi-thread? */
	static unsigned int currency_id = 0;

	return currency_id++;
}


static struct currency_t *new_currency(void)
{
	struct currency_t *c = malloc(sizeof(struct currency_t));

	memset(c, 0, sizeof(struct currency_t));
	c->o_id = get_currency_id();

	return c;
}

static void free_currency(struct currency_t *c)
{
	free(c);
}

/* name=xxx&rate=xxx&rate2=xxx */
static int str2currency(const char *str, struct currency_t *c)
{
	char buf[128] = {0};
	char name[MAX_OBJECT_NAME_SIZE] = {0};
	int r, len;
	double rate, rate2;

	len = strlen(str);
	r = mg_get_var(str, len, "name", buf, 128);
	if (r == -1)
		return -1;
	strcpy(name, buf);

	/* we trust the client-side */

	r = mg_get_var(str, len, "rate", buf, 128);
	if (r == -1)
		return -1;
	rate = atof(buf);
	if (rate < 0.0)
		return -1;

	rate2 = 1.0;
	r = mg_get_var(str, len, "rate2", buf, 128);
	if (r != -1) {
		rate2 = atof(buf);
		if (rate2 < 0.0)
			return -1;
	}

	strcpy(c->o_name, name);
	c->rate = rate;
	c->rate2 = rate2;

	return 0;
}

static int currency2json(char *json, struct currency_t *c)
{
	int len;

	/* {"id":xxx,"name":"EUR","rate":xxx,"rate2":xxx} */
	len = sprintf(json, "{\"id\":%u,\"name\":\"%s\",\"rate\":%lf,\"rate2\":%lf}",
			c->o_id, c->o_name, c->rate, c->rate2);
	return len;
}

/* URI handlers */

/* add currency. accepts GET
 * the query string is:
 * name=xxx&rate=xxx&rate2=xxx
 * where the rate2 is optional
 */
int uh_add_currency(struct mg_connection *conn,
		const struct mg_request_info *ri,
		const char *uri,
		int mobile)
{
	struct currency_t *c;
	int len, r;
	char *req = ri->query_string;

	printf("%s\n", __func__);
	printf("method: %s\n", ri->request_method);
	printf("request: %s\n", ri->query_string);
	if (req == NULL)
		return -1;
	len = strlen(req);

	c = new_currency();
	r = str2currency(req, c);
	printf("name = %s, rate = %f\n", c->o_name, c->rate);
	if (r != -1)
		LIST_INSERT_HEAD(&currencies, &c->obj, entries);
	else
		free_currency(c);

	JSON_START();
	mg_printf(conn, r == -1 ? "NOK" : "OK");

	return 0;
}

static void
process_currency(struct mg_connection *conn, void *obj)
{
	struct currency_t *c = obj;

	/* {"id":xxx,"name":"EUR","rate":xxx,"rate2":xxx} */
	mg_printf(conn, "{\"id\":%u,\"name\":\"%s\",\"rate\":%lf,\"rate2\":%lf},",
			c->o_id, c->o_name, c->rate, c->rate2);
}

/* query all currency instances
 * support GET only  
 * the filter could be:
 * name=xxx and/or id=xxx
 */
int uh_query_currency(struct mg_connection *conn,
		const struct mg_request_info *ri,
		const char *uri,
		int mobile)
{
	JSON_START();

	mg_printf(conn, "[");

	query_object(conn, ri, uri, mobile, &currencies, process_currency);

	/* a dummy tail */
	mg_printf(conn, "{\"id\":-1,\"name\":\"DUMMY\",\"rate\":1.0,\"rate2\":1.0}");
	mg_printf(conn, "]");

	return 0;
}

static void
delete_currency(struct mg_connection *conn, void *obj)
{
	struct object_t *c = obj;

	LIST_REMOVE(c, entries);
}

/* GET request which must have var id */
int uh_del_currency(struct mg_connection *conn,
		const struct mg_request_info *ri,
		const char *uri,
		int mobile)
{
	JSON_START();
	query_object(conn, ri, uri, mobile, &currencies, delete_currency);
	mg_printf(conn, "OK");

	return 0;
}

